package com.wenjie.plugin;

import android.Manifest;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;

import com.alibaba.fastjson.JSON;
import com.pantum.lld.DeviceInfo;
import com.pantum.lld.DeviceManager;
import com.pantum.lld.PrintSetting;
import com.wenjie.plugin.config.Common;
import com.wenjie.plugin.entity.MyUsbDevice;
import com.wenjie.plugin.entity.PrintFile;
import com.wenjie.plugin.entity.PrinterConfig;
import com.wenjie.plugin.entity.Result;
import com.wenjie.plugin.entity.UsbDeviceConfig;
import com.wenjie.plugin.service.SystemService;
import com.wenjie.plugin.util.ConfigurationUtil;
import com.wenjie.plugin.util.FileUtil;
import com.wenjie.plugin.util.Global;
import com.wenjie.plugin.util.UsbDeviceUtil;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

import io.dcloud.common.core.permission.PermissionControler;
import io.dcloud.feature.uniapp.annotation.UniJSMethod;
import io.dcloud.feature.uniapp.common.UniModule;

/**
 * UniApp Module扩展
 * 打印 Module
 */
public class PrinterModule extends UniModule {

    /**
     * 权限申请Code
     */
    private static final int PERMISSION_CODE = 12345;

    /**
     * 要申请的权限
     */
    private static final String[] permissionArray = new String[]{
            Manifest.permission.INTERNET,
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WAKE_LOCK,
            Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS,
            Manifest.permission.RECEIVE_BOOT_COMPLETED,
    };

    /**
     * 申请权限
     */
    @UniJSMethod(uiThread = true)
    public void requestPermissions() {
        if (mUniSDKInstance.getContext() != null) {
            Activity activity = (Activity) mUniSDKInstance.getContext();
            PermissionControler.requestPermissions(activity, permissionArray, PERMISSION_CODE);
        }
    }

    /**
     * 权限申请结果
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        if (requestCode == PERMISSION_CODE) {
            Global global = Global.getInstance();

            global.setHasAllPermission(permissions.length == grantResults.length);
        }

        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    /**
     * 判断是否获得全部权限
     */
    @UniJSMethod(uiThread = false)
    public Result<String> hasAllPermission() {
        Global global = Global.getInstance();

        boolean hasAllPermission = global.isHasAllPermission();
        if (!Boolean.TRUE.equals(hasAllPermission)) {
            if (mUniSDKInstance.getContext() != null) {
                Activity activity = (Activity) mUniSDKInstance.getContext();
                PermissionControler.requestPermissions(activity, permissionArray, PERMISSION_CODE);
            }
        }

        Result<String> result = new Result<>();
        result.setSuccess(global.isHasAllPermission());
        result.setMessage("方法调用成功");

        return result;
    }

    /**
     * 获取所有的USB设备
     */
    @UniJSMethod(uiThread = false)
    public Result<List<MyUsbDevice>> getAllUsbDevice() {
        UsbDeviceUtil.getAllUsbDevice();

        Global global = Global.getInstance();
        Result<List<MyUsbDevice>> result = new Result<>();

        List<UsbDevice> usbDeviceList = global.getUsbDeviceList();
        List<MyUsbDevice> targetList = new ArrayList<>();

        if (usbDeviceList != null) {
            for (UsbDevice usbDevice : usbDeviceList) {
                MyUsbDevice myUsbDevice = new MyUsbDevice();
                myUsbDevice.setDeviceId(usbDevice.getDeviceId());
                myUsbDevice.setDeviceName(usbDevice.getProductName());

                targetList.add(myUsbDevice);
            }

            result.setSuccess(true);
            result.setMessage("接口调用成功");
            result.setData(targetList);

            return result;
        } else {
            result.setSuccess(false);
            result.setMessage("主机未连接任何USB设备");

            return result;
        }
    }

    /**
     * 设置打印机设备
     */
    @UniJSMethod(uiThread = false)
    public Result<String> handleSetPrinter(UsbDeviceConfig config) {
        Global global = Global.getInstance();

        Result<String> result = new Result<>();

        DeviceManager printDevice = global.getPrintDevice();
        if (printDevice == null) {
            result.setSuccess(false);
            result.setMessage("打印机未正确初始化，请重启此应用并再次尝试");
            return result;
        }

        if (config == null || config.getUsbDeviceId() == null) {
            result.setSuccess(false);
            result.setMessage("请选择打印机设备");
            return result;
        }

        List<UsbDevice> usbDeviceList = global.getUsbDeviceList();
        final int finalUsbDeviceId = config.getUsbDeviceId();
        Optional<UsbDevice> usbDeviceOptional = usbDeviceList.stream().filter(item -> Objects.equals(item.getDeviceId(), finalUsbDeviceId)).findAny();
        if (usbDeviceOptional.isEmpty()) {
            result.setSuccess(false);
            result.setMessage("所选择的USB设备不存在");
            return result;
        }

        UsbDevice usbDevice = usbDeviceOptional.get();
        Context mContext = global.getContext();

        UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
        if (!usbManager.hasPermission(usbDevice)) {
            // 没有权限，申请权限
            PendingIntent permissionIntent = PendingIntent.getBroadcast(
                    mContext,
                    110,
                    new Intent("com.wenjie.ACTION_USB_PERMISSION"),
                    PendingIntent.FLAG_IMMUTABLE
            );
            usbManager.requestPermission(usbDevice, permissionIntent);

            result.setSuccess(false);
            result.setMessage("请点击允许使用此USB设备，并再次提交");

            return result;
        }

        final int fileDescriptor = usbManager.openDevice(usbDevice).getFileDescriptor();
        final int productId = usbDevice.getProductId();
        final int vendorId = usbDevice.getVendorId();
        final String productName = usbDevice.getProductName();

        DeviceInfo deviceInfo = new DeviceInfo(productName, productName, 2, String.valueOf(fileDescriptor), false);

        boolean setResult = printDevice.setDevice(deviceInfo);
        if (setResult) {
            // 保存打印机配置
            ConfigurationUtil configurationUtil = global.getConfigurationUtil();
            configurationUtil.putInt(Common.PRINTER_PID, productId);
            configurationUtil.putInt(Common.PRINTER_VID, vendorId);

            global.setConfigPrinter(true);

            result.setSuccess(true);
            result.setMessage("打印机设置成功");
            return result;
        } else {
            result.setSuccess(false);
            result.setMessage("打印机设置失败，请稍后重试");
            return result;
        }
    }

    /**
     * 获取打印机能力
     */
    @UniJSMethod(uiThread = false)
    public Result<String> getPrinterAbility() {
        Global global = Global.getInstance();

        Result<String> result = new Result<>();

        DeviceManager printDevice = global.getPrintDevice();
        if (printDevice == null) {
            result.setSuccess(false);
            result.setMessage("打印机未正确初始化，请重启此应用并再次尝试");

            return result;
        }

        String deviceCapability = printDevice.getDeviceCapability();

        result.setSuccess(true);
        result.setData(deviceCapability);
        return result;
    }

    /**
     * 打印机配置
     */
    @UniJSMethod(uiThread = false)
    public Result<String> configPrinter(PrinterConfig printerConfig) {
        Global global = Global.getInstance();

        Result<String> result = new Result<>();

        if (!Boolean.TRUE.equals(global.isConfigPrinter())) {
            result.setSuccess(false);
            result.setMessage("打印机未正确配置");
            return result;
        }

        DeviceManager printDevice = global.getPrintDevice();
        if (printDevice == null) {
            result.setSuccess(false);
            result.setMessage("打印机未正确初始化，请重启此应用并再次尝试");
            return result;
        }

        if (printerConfig == null) {
            result.setSuccess(false);
            result.setMessage("打印机配置参数异常");
            return result;
        }

        Integer numOfCopies = printerConfig.getNumOfCopies();
        if (numOfCopies == null || numOfCopies <= 0) {
            result.setSuccess(false);
            result.setMessage("打印数量配置不正确");
            return result;
        }

        String mode = printerConfig.getMode();
        if (mode == null || mode.isEmpty() || mode.trim().isEmpty()) {
            result.setSuccess(false);
            result.setMessage("打印色彩配置不正确");
            return result;
        }

        String duplex = printerConfig.getDuplex();
        if (duplex == null || duplex.isEmpty() || duplex.trim().isEmpty()) {
            result.setSuccess(false);
            result.setMessage("请正确配置单面打印或双面打印");
            return result;
        }

        String collate = printerConfig.getCollate();
        if (collate == null || collate.isEmpty() || collate.trim().isEmpty()) {
            result.setSuccess(false);
            result.setMessage("请正确配置逐份打印参数");
            return result;
        }

        String paper = printerConfig.getPaper();
        if (paper == null || paper.isEmpty() || paper.trim().isEmpty()) {
            result.setSuccess(false);
            result.setMessage("请正确配置纸张尺寸");
            return result;
        }

        String feeder = printerConfig.getFeeder();
        if (feeder == null || feeder.isEmpty() || feeder.trim().isEmpty()) {
            result.setSuccess(false);
            result.setMessage("请配置纸张来源");
            return result;
        }

        PrintSetting printSetting = new PrintSetting();
        printSetting.gammaIndex = 0x00;
        printSetting.halftoneIndex = 0x00;
        printSetting.numOfCopies = numOfCopies;
        printSetting.collate = collate;
        printSetting.feeder = feeder;
        printSetting.paper = paper;
        printSetting.duplex = duplex;
        printSetting.mode = mode;
        printSetting.paperType = "";

        boolean setResult = printDevice.setPrintSetting(printSetting);
        if (setResult) {
            // 将配置保存到配置文件
            String printSettingString = JSON.toJSONString(printerConfig);

            ConfigurationUtil configurationUtil = global.getConfigurationUtil();
            configurationUtil.putString(Common.PRINT_CONFIG, printSettingString);

            result.setSuccess(true);
            result.setMessage("打印机配置成功");

            return result;
        } else {
            result.setSuccess(false);
            result.setMessage("打印机配置失败，请稍后重试");

            return result;
        }
    }

    /**
     * 添加打印文件
     */
    @UniJSMethod(uiThread = false)
    public Result<String> addPrintFile(PrintFile printFile) {
        Result<String> result = new Result<>();
        if (printFile == null) {
            result.setSuccess(false);
            result.setMessage("打印图片资源为空");

            return result;
        }

        String fileBase64 = printFile.getFileBase64();

        Global global = Global.getInstance();

        if (!Boolean.TRUE.equals(global.isConfigPrinter())) {
            result.setSuccess(false);
            result.setMessage("打印机未正确配置");

            return result;
        }

        DeviceManager printDevice = global.getPrintDevice();
        if (printDevice == null) {
            result.setSuccess(false);
            result.setMessage("打印机未正确初始化，请重启此应用并再次尝试");

            return result;
        }

        if (fileBase64 == null || fileBase64.isEmpty()) {
            result.setSuccess(false);
            result.setMessage("请添加要打印的图片资源");

            return result;
        }

        Context mContext = global.getContext();

        FileUtil fileUtil = new FileUtil(mContext);
        Boolean saveResult = fileUtil.saveBase64ToFile(fileBase64);
        if (Boolean.TRUE.equals(saveResult)) {
            result.setSuccess(true);
            result.setMessage("添加成功");

            return result;
        }

        result.setSuccess(false);
        result.setMessage("添加失败");

        return result;
    }

    /**
     * 开始打印
     */
    @UniJSMethod(uiThread = false)
    public Result<String> startPrint() {
        Global global = Global.getInstance();

        Result<String> result = new Result<>();

        if (!Boolean.TRUE.equals(global.isConfigPrinter())) {
            result.setSuccess(false);
            result.setMessage("打印机未正确配置");

            return result;
        }

        DeviceManager printDevice = global.getPrintDevice();
        if (printDevice == null) {
            result.setSuccess(false);
            result.setMessage("打印机未正确初始化，请重启此应用并再次尝试");

            return result;
        }

        // 获取打印配置
        ConfigurationUtil configurationUtil = global.getConfigurationUtil();
        String printConfigStr = configurationUtil.getString(Common.PRINT_CONFIG, null);
        if (printConfigStr == null) {
            result.setSuccess(false);
            result.setMessage("请先配置打印参数");

            return result;
        }

        PrintSetting printSetting = JSON.parseObject(printConfigStr, PrintSetting.class);
        if (printSetting == null) {
            result.setSuccess(false);
            result.setMessage("打印参数失效，请先配置打印参数");

            return result;
        }

        Context mContext = global.getContext();
        FileUtil fileUtil = new FileUtil(mContext);

        // 提取出所有待打印文件
        List<File> fileList = fileUtil.getAllFile();
        if (fileList == null || fileList.isEmpty()) {
            result.setSuccess(false);
            result.setMessage("请先上传要打印的图片文件");

            return result;
        }

        for (File file : fileList) {
            String path = file.getPath();
            printDevice.enqueuePrintFile(path);
        }

        printDevice.enqueuePrintFile(null);
        DeviceManager.PrintResult printResult = printDevice.startPrint();

        // 打印成功，清空打印文件夹
        if (printResult == DeviceManager.PrintResult.SUCCESS) {
            fileUtil.clearFolder();

            result.setSuccess(true);
            result.setMessage("打印成功");

            return result;
        }

        result.setSuccess(false);
        result.setMessage("打印失败，请稍后重试");

        return result;
    }

    /**
     * 清空打印队列
     */
    @UniJSMethod(uiThread = false)
    public Result<String> clearPrintQueue() {
        Global global = Global.getInstance();
        Context mContext = global.getContext();

        Result<String> result = new Result<>();

        if (!Boolean.TRUE.equals(global.isConfigPrinter())) {
            result.setSuccess(false);
            result.setMessage("打印机未正确配置");

            return result;
        }

        DeviceManager printDevice = global.getPrintDevice();
        if (printDevice == null) {
            result.setSuccess(false);
            result.setMessage("打印机未正确初始化，请重启此应用并再次尝试");

            return result;
        }

        boolean clearResult = printDevice.clearPrintEnqueueFile();
        if (clearResult) {
            // 清空打印文件夹
            FileUtil fileUtil = new FileUtil(mContext);
            fileUtil.clearFolder();

            result.setSuccess(true);
            result.setMessage("打印队列清除成功");

            return result;
        } else {
            result.setSuccess(false);
            result.setMessage("打印队列清除失败，请稍后重试");

            return result;
        }
    }

    /**
     * 取消打印
     */
    @UniJSMethod(uiThread = false)
    public Result<String> cancelPrint() {
        Global global = Global.getInstance();
        Context mContext = global.getContext();

        Result<String> result = new Result<>();

        if (!Boolean.TRUE.equals(global.isConfigPrinter())) {
            result.setSuccess(false);
            result.setMessage("打印机未正确配置");

            return result;
        }

        DeviceManager printDevice = global.getPrintDevice();
        if (printDevice == null) {
            result.setSuccess(false);
            result.setMessage("打印机未正确初始化，请重启此应用并再次尝试");

            return result;
        }

        boolean cancelResult = printDevice.cancelPrint();
        if (cancelResult) {
            // 清空打印文件夹
            FileUtil fileUtil = new FileUtil(mContext);
            fileUtil.clearFolder();

            result.setSuccess(true);
            result.setMessage("取消成功");

            return result;
        } else {
            result.setSuccess(false);
            result.setMessage("取消失败");

            return result;
        }
    }

    /**
     * 启动前台服务
     */
    @UniJSMethod(uiThread = true)
    public void startService() {
        Global global = Global.getInstance();
        Context mContext = global.getContext();

        Intent serviceIntent = new Intent(mContext, SystemService.class);
        mContext.startForegroundService(serviceIntent);
    }

    /**
     * 退出应用
     */
    @UniJSMethod(uiThread = true)
    public void exit() {
        Global global = Global.getInstance();
        Context mContext = global.getContext();

        Intent serviceIntent = new Intent(mContext, SystemService.class);
        mContext.stopService(serviceIntent);

        System.exit(0);
    }

    /**
     * 检查指定的服务是否在运行
     *
     * @param serviceClass 服务的类
     * @return true 如果服务正在运行，否则 false
     */
    private boolean isServiceRunning(Class<?> serviceClass, Context mContext) {
        ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
        if (activityManager != null) {
            // 获取所有正在运行的服务
            for (ActivityManager.RunningServiceInfo service : activityManager.getRunningServices(Integer.MAX_VALUE)) {
                if (serviceClass.getName().equals(service.service.getClassName())) {
                    // 服务正在运行
                    return true;
                }
            }
        }

        // 服务未运行
        return false;
    }
}
